#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#include <dybuf.h>
#include <tokenhelper.h>
#include <strhelper.h>

bool tk_next(TokenIn& in, TokenOut& out)
{
    if (in.dybuf == NULL)
        return false;

    DyBuf *dybuf = in.dybuf;
    int    len   = dybuf->get_size();
    char  *ptr   = dybuf->get_buf();
    int    i;
    char   c;

    if (len <= 0)
        return false;

    // ignore leading delimiters and comments
    i = 0;
    while (i < len) {
        c = ptr[i];
        if (c == in.comment_char) {
            ++i;
            while (i < len && (c = ptr[i]) != '\n')
                ++i;
            if (c == '\n') {
                ++in.lineno;
                ++i;
            }
        }
        else {
            if (!strchr(in.delimiter.c_str(), c))
                break;

            if (c == '\n')
                ++in.lineno;

            ++i;
        }
    }

    if (i == len) {
        dybuf->drop_first(len);
        return false;
    }

    std::string& text = out.text;

    out.lineno = in.lineno;
    text.clear();

    if (in.handle_quote_string && c == '"') {
        char *end;

        ++i;
        str_get_escape_str_until(ptr + i, '"', text, &end);

        int slen = end - (ptr + i);

        in.lineno += str_get_char_cnt(ptr + i, slen, '\n');

        i += slen + 1;
    }
    else {
        for (; i < len; i++) {
            c = ptr[i];

            if (strchr(in.delimiter.c_str(), c) || c == in.comment_char)
                break;

            if (c == '\n')
                ++in.lineno;

            text.push_back(c);
        }
    }

    in.dybuf->drop_first(i);

    return true;
}
